
void Main(string arguments){
    
}

Program(){
	Runtime.UpdateFrequency = UpdateFrequency.Update1;
}

class Block
{
    // == 构造方法
    public Block(IMyTerminalBlock b){
        this._block = b;
    }

    // == 成员属性
    public IMyTerminalBlock _block; //方块
    public long Id{ //唯一ID
        get { return this._block.EntityId; }
    }
    public bool IsOK{ //是否正确获取到方块
        get { return this._block != null; }
    }
    public bool IsBeingHacked{ //是否被黑了
        get { return this._block.IsBeingHacked; }
    }
    public bool IsFunctional{ //是否可以工作
        get { return this._block.IsFunctional; }
    }
    public bool IsWorking{ //是否在工作
        get { return this._block.IsWorking; }
    }
    public int NumberInGrid{ //在网格中的顺序
        get { return this._block.NumberInGrid; }
    }
    public IMyCubeGrid Grid{ //所属网格
        get { return this._block.CubeGrid; }
    }
    public string Name{ //自定义名称（CustomName）
        get { return this._block.CustomName; }
        set { this._block.CustomName = value; }
    }
    public string Data{ //自定义数据 （CustomData）
        get { return this._block.CustomData; }
        set { this._block.CustomData = value; }
    }
    public long OwnerId{ //所有人ID
        get { return this._block.OwnerId; }
    }
    public Vector3D Position{ //坐标（基于世界绝对坐标系的坐标）
        get { return this._block.GetPosition(); }
    }
    // public WorldMatrix Matrix{ //矩阵（描述方块世界坐标几方位的矩阵）
    //     get { return this._block.WorldMatrix; }
    // }
    public Vector3D Forward{ //前向矢量（归一化的，即矢量的长度恒等于1）
        get { return this._block.WorldMatrix.Forward; }
    }
    public Vector3D Backward{ //后向矢量（归一化的，即矢量的长度恒等于1）
        get { return this._block.WorldMatrix.Backward; }
    }
    public Vector3D Left{ //左向矢量（归一化的，即矢量的长度恒等于1）
        get { return this._block.WorldMatrix.Left; }
    }
    public Vector3D Right{ //右向矢量（归一化的，即矢量的长度恒等于1）
        get { return this._block.WorldMatrix.Right; }
    }
    public Vector3D Up{ //上向矢量（归一化的，即矢量的长度恒等于1）
        get { return this._block.WorldMatrix.Up; }
    }
    public Vector3D Down{ //下向矢量（归一化的，即矢量的长度恒等于1）
        get { return this._block.WorldMatrix.Down; }
    }
    public bool ShowInTerminal{ //是否在终端显示
        get { return this._block.ShowInTerminal; }
        set { this._block.ShowInTerminal = value; }
    }
    public bool ShowInInventory{ //是否在库存中显示
        get { return this._block.ShowInInventory; }
        set { this._block.ShowInInventory = value; }
    }
}

class Cockpit: Block
{
    // v1.0.0
    // 依赖：Block类

    // == 构造方法
    public Cockpit(IMyTerminalBlock b):base(b){
        this._block = b;
        this._cockpit = b as IMyShipController;
    }
    public Cockpit(IMyShipController b):base(b){
        this._block = b;
        this._cockpit = b as IMyShipController;
    }

    // == 成员属性
    public IMyShipController _cockpit; //主控块
    public bool CanControlShip{ //是否可以控制飞船
        get { return this._cockpit.CanControlShip; }
    }
    public bool IsUnderControl{ //是否正在被玩家控制
        get { return this._cockpit.IsUnderControl; }
    }
    public bool HasWheels{ //是否有轮子
        get { return this._cockpit.HasWheels; }
    }
    public bool ControlWheels{ //是否勾选了可以控制轮子
        get { return this._cockpit.ControlWheels; }
        set { this._cockpit.ControlWheels = value; }
    }
    public bool ControlThrusters{ //是否勾选了可以控制推进器
        get { return this._cockpit.ControlThrusters; }
        set { this._cockpit.ControlThrusters = value; }
    }
    public bool HandBrake{ //是否勾选了手刹
        get { return this._cockpit.HandBrake; }
        set { this._cockpit.HandBrake = value; }
    }
    public bool DampenersOverride{ //是否勾选了惯性抑制
        get { return this._cockpit.DampenersOverride; }
        set { this._cockpit.DampenersOverride = value; }
    }
    public bool IsMainCockpit{ //是否是主控
        get { return this._cockpit.IsMainCockpit; }
        set { this._cockpit.IsMainCockpit = value; }
    }
    public bool ShowHorizonIndicator{ //是否勾选了显示地平线高度
        get { return this._cockpit.ShowHorizonIndicator; }
        set { this._cockpit.ShowHorizonIndicator = value; }
    }
    public Vector3D InputKey{ //按键输入，X表示AD，Y表示空格和C，Z表示SW
        get {
            Vector3D temp = new Vector3D();
            Vector3D.TryParse(this._cockpit.MoveIndicator.ToString(), out temp);
            return temp;
        }
    }
    public double InputRoll{ //QE按键输入
        get { return (double)this._cockpit.RollIndicator; }
    }
    public Vector2D InputMouse{ //鼠标输入，X表示左右，Y表示上下
        get {
            return new Vector2D((double)this._cockpit.RotationIndicator.X, (double)this._cockpit.RotationIndicator.Y);
        }
    }
    public Vector3D CenterOfMass{ //质心（不考虑活塞转子等外挂部分）
        get { return this._cockpit.CenterOfMass; }
    }
    public double BaseMass{ //飞船基础质量
        get { return this._cockpit.CalculateShipMass().BaseMass; }
    }
    public double TotalMass{ //飞船总体质量
        get { return this._cockpit.CalculateShipMass().TotalMass; }
    }
    public double PhysicalMass{ //飞船物理质量
        get { return this._cockpit.CalculateShipMass().PhysicalMass; }
    }
    public Vector3D ArtificialGravity{ //人工重力
        get { return this._cockpit.GetArtificialGravity(); }
    }
    public Vector3D NaturalGravity{ //自然重力
        get { return this._cockpit.GetNaturalGravity(); }
    }
    public Vector3D Velocity{ //飞船线速度矢量
        get { return this._cockpit.GetShipVelocities().LinearVelocity; }
    }
    public Vector3D AngleVelocity{ //飞船角速度矢量
        get { return this._cockpit.GetShipVelocities().AngularVelocity; }
    }
    public bool IsInPlanet{ //是否在星球上
        get {
            Vector3D temp = new Vector3D();
            return this._cockpit.TryGetPlanetPosition(out temp);
        }
    }
    public Vector3D PlanetPosition{ //所处的星球坐标（处于星球状态中才能获取）
        get {
            Vector3D temp = new Vector3D();
            this._cockpit.TryGetPlanetPosition(out temp);
            return temp;
        }
    }
    public double PlanetElevationSealevel{ //所处的星球海平面高度（处于星球状态中才能获取）
        get{
            double e = 0;
            this._cockpit.TryGetPlanetElevation(MyPlanetElevation.Sealevel, out e);
            return e;
        }
    }
    public double PlanetElevationSurface{ //所处的星球地表高度（处于星球状态中才能获取）
        get{
            double e = 0;
            this._cockpit.TryGetPlanetElevation(MyPlanetElevation.Surface, out e);
            return e;
        }
    }
}

class LCD: Block
{
    // v1.0.0
    // 依赖：Block类

    // == 构造方法
    public LCD(IMyTerminalBlock b):base(b){
        this._block = b;
        this._lcd = b as IMyTextPanel;
    }
    public LCD(IMyTextPanel b):base(b){
        this._block = b;
        this._lcd = b as IMyTextPanel;
    }

    // == 成员属性
    public IMyTextPanel _lcd; //lcd方块
    public string Title{
        get { return this._lcd.GetPublicTitle(); }
        set { this._lcd.WritePublicTitle(value); }
    }
    public string Text{
        get { return this._lcd.GetPublicText(); }
        set { this._lcd.WritePublicText(value); }
    }
    public bool ShowText{
        get { return this._lcd.GetValueBool("ShowTextOnScreen"); }
        set { this._lcd.SetValue("ShowTextOnScreen", value); }
    }

    // == 成员方法
    public void AppendText(string str){
        this._lcd.WritePublicText(str, true);
    }
}

class Rotor: Block
{
    // v1.0.0
    // 依赖：Block类

    // == 构造方法
    public Rotor(IMyTerminalBlock b):base(b){
        this._block = b;
        this._rotor = b as IMyMotorStator;
    }
    public Rotor(IMyMotorStator b):base(b){
        this._block = b;
        this._rotor = b as IMyMotorStator;
    }
    // == 静态方法
    // 角度转换
    public static double AngleToRad(double angle){
        return angle*Math.PI/180;
    }
    public static double RadToAngle(double rad){
        return rad*180/Math.PI;
    }
    public static double NormalizeAngle(double angle){
        if(angle > 360){
            return angle%360;
        }else if(angle < 0){
            return 360 + (angle%360);
        }else{
            return angle;
        }
    }


    // == 成员属性
    public IMyMotorStator _rotor; //转子方块
    public double Angle{
        get { return Rotor.RadToAngle(this._rotor.Angle); }
    }
    public double AngleRad{
        get { return this._rotor.Angle; }
    }
    public double Velocity{
        get { return this._rotor.TargetVelocityRPM; }
        set { this._rotor.TargetVelocityRPM = (float)value; }
    }
    public double VelocityRad{
        get { return this._rotor.TargetVelocityRad; }
        set { this._rotor.TargetVelocityRad = (float)value; }
    }
    public double VelocityAngle{
        get { return Rotor.RadToAngle(this._rotor.TargetVelocityRad); }
        set { this._rotor.TargetVelocityRad = (float)Rotor.AngleToRad(value); }
    }

    // == 成员方法

    // 转到某个角度
    // input angle 目标角度，使用角度而不是弧度
    // input mode 运动方式，1顺时针，-1逆时针，0自动
    // input velocity 指定速度，不指定默认用PID
    public double TurnToAngleAccuracy = 0.2; //转动抵达判定角度
    public double TurnToVelocityAccuracy = 0.01; //转动抵达判定速度
    public double turn_pid_p = 20; //比例系数
    public double turn_pid_i = 20; //积分系数(增加后降低动态误差，增加震荡)
    public double turn_pid_d = 30; //微分系数（增加后降低震荡）
    public double turn_pid_t = 30; //误差累加控制周期
    private List<double> turn_pid_diff_data = new List<double>();
    public bool TurnTo(double angle = 0, int mode = 0, double velocity = 0){
        angle = Rotor.NormalizeAngle(angle);

        if(mode == 0){
            if(angle > this.Angle){
                mode = angle - this.Angle > 180 ? -1 : 1;
            }else{
                mode = this.Angle - angle > 180 ? 1 : -1;
            }
        }

        //指定速度方式
        if(velocity != 0){
            this.Velocity = mode * velocity;
            return Math.Abs(angle - this.Angle) <= 0.5;
        }

        // diff是当前角度和目标角度的转动角度差，范围是0-1
        double diff = 0;
        if(mode == 1){
            if(angle > this.Angle){
                diff = angle - this.Angle;
            }else{
                diff = (360 - this.Angle) + angle;
            }
        }else if(mode == -1){
            if(this.Angle > angle){
                diff = this.Angle - angle;
            }else{
                diff = this.Angle + (360 - angle);
            }
        }
        diff /= 360;

        //对角度差进行逐帧累加，累加次数为 PID控制积分系数
        double diff_i = 0; //积分求和项
        if(this.turn_pid_diff_data.Count >= this.turn_pid_t){
            this.turn_pid_diff_data.Remove(this.turn_pid_diff_data[0]);
        }
        this.turn_pid_diff_data.Add(diff);
        foreach(double d in this.turn_pid_diff_data){
            diff_i += d;
        }

        //输出结果是
        this.Velocity = mode*this.turn_pid_p*(diff + diff_i*this.turn_pid_i/turn_pid_t + (diff - this.turn_pid_diff_data[this.turn_pid_diff_data.Count-1])*this.turn_pid_d);

        return diff*360 <= this.TurnToAngleAccuracy && Math.Abs(this.Velocity) <= this.TurnToVelocityAccuracy;
    }
    
}

class Wheel: Block
{
    // v1.0.0
    // 依赖：Block类

    // == 构造方法
    public Wheel(IMyTerminalBlock b):base(b){
        this._block = b;
        this._wheel = b as IMyMotorSuspension;
    }
    public Wheel(IMyMotorSuspension b):base(b){
        this._block = b;
        this._wheel = b as IMyMotorSuspension;
    }

    // == 成员属性
    public IMyMotorSuspension _wheel;
    public bool SteeringOnOff{ //是否允许转向
        get { return this._wheel.Steering; }
        set { this._wheel.Steering = value; }
    }
    public bool PropulsionOnOff{ //是否允许加速
        get { return this._wheel.Propulsion; }
        set { this._wheel.Propulsion = value; }
    }
    public bool InvertSteerOnOff{ //是否反向转向
        get { return this._wheel.InvertSteer; }
        set { this._wheel.InvertSteer = value; }
    }
    public bool InvertPropulsionOnOff{ //是否反向加速
        get { return this._wheel.InvertPropulsion; }
        set { this._wheel.InvertPropulsion = value; }
    }
    public double Power{ //功率
        get { return this._wheel.Power; }
        set { this._wheel.Power = (float)value; }
    }
    public double Strength{ //强度
        get { return this._wheel.Strength; }
        set { this._wheel.Strength = (float)value; }
    }
    public double Friction{ //摩擦力
        get { return this._wheel.Friction; }
        set { this._wheel.Friction = (float)value; }
    }
    public double SpeedLimit{ //速度限制，0~360，其中360为无限制
        get { return this._wheel.GetValueFloat("Speed Limit"); }
        set { this._wheel.SetValueFloat("Speed Limit", (float)value); }
    }
    public double Speed{ //加速越级值
        get { return this._wheel.GetValueFloat("Propulsion override"); }
        set { this._wheel.SetValueFloat("Propulsion override", (float)value); }
    }
    public double Steer{ //转向越级值
        get { return this._wheel.GetValueFloat("Steer override"); }
        set { this._wheel.SetValueFloat("Steer override", (float)value); }
    }
    public double Height{ //悬架高度
        get { return this._wheel.Height; }
        set { this._wheel.Height = (float)value; }
    }

}

class Weapon: Block
{
    // v1.0.0
    // 依赖：Block类

    // == 构造方法
    public Weapon(IMyTerminalBlock b):base(b){
        this._block = b;
        this._weapon = b as IMyUserControllableGun;
    }
    public Weapon(IMyUserControllableGun b):base(b){
        this._block = b;
        this._weapon = b as IMyUserControllableGun;
    }

    // == 成员属性
    public IMyUserControllableGun _weapon;
    public bool IsShooting{ //是否在射击
        get { return this._weapon.IsShooting; }
    }

    // ==== 成员方法
    public void Shoot(){
        this._weapon.ApplyAction("ShootOnce");
    }
}

class Camera: Block
{
    // v1.0.0
    // 依赖：Block类

    // == 构造方法
    public Camera(IMyTerminalBlock b):base(b){
        this._block = b;
        this._camera = b as IMyCameraBlock;
    }
    public Camera(IMyCameraBlock b):base(b){
        this._block = b;
        this._camera = b as IMyCameraBlock;
    }

    // == 成员属性
    public IMyCameraBlock _camera;
    public bool IsActive{ //是否可用
        get { return this._camera.IsActive; }
    }
    public bool EnableRaycast{ //是否开启允许扫描
        get { return this._camera.EnableRaycast; }
        set { this._camera.EnableRaycast = value; }
    }
    public double CanScanRange{ //可扫描距离，储能
        get { return this._camera.AvailableScanRange; }
    }

    // == 成员方法
    public bool CanScan(double distance){
        return this._camera.CanScan(distance);
    }
    public bool CanScan(Vector3D point){
        return this._camera.CanScan(point);
    }
    public bool CanScan(double distance, Vector3D direction){
        return this._camera.CanScan(distance, direction);
    }
    public Camera.Target Scan(Vector3D targetPos){
        return new Camera.Target(this._camera.Raycast(targetPos));
    }
    public Camera.Target Scan(double distance, Vector3D targetDirection){
        return new Camera.Target(this._camera.Raycast(distance, targetDirection));
    }
    public Camera.Target Scan(double distance, double pitch = 0, double yaw = 0){
        return new Camera.Target(this._camera.Raycast(distance, (float)pitch, (float)yaw));
    }

    // == 成员类
    public class Target
    {
        // == 构造方法
        public Target(MyDetectedEntityInfo entity, int create_time = 0){
            this._target = entity;
            this.CreateTime = create_time;
        }

        // == 成员属性
        public MyDetectedEntityInfo _target;
        public int CreateTime; //创建时间
        public int UpdateTime; //更新时间
        public bool IsEmpty{ //是否是空目标
            get { return this._target.EntityId == 0L; }
        }
        public long Id { //实体ID
            get { return this._target.EntityId; }
        }
        public string Name{ //名字
            get { return this._target.Name; }
        }
        public Vector3D HitPosition{ //探测射线或探测场与实体的碰撞坐标
            get {
                Vector3D temp = new Vector3D();
                Vector3D.TryParse(this._target.HitPosition.ToString(), out temp);
                return temp;
            }
        }
        public Vector3D Position{ //质心的空间坐标
            get { return this._target.BoundingBox.Center; }
        }
        public Vector3D Velocity{ //速度矢量
            get {
                Vector3D temp = new Vector3D();
                Vector3D.TryParse(this._target.Velocity.ToString(), out temp);
                return temp;
            }
        }
        public BoundingBoxD Box{ //空间体容器
            get { return this._target.BoundingBox; }
        }
        public MyRelationsBetweenPlayerAndBlock Relationship{ //阵营关系
            get { return this._target.Relationship; }
        }
    
        // == 成员方法
        // 更新目标状态和时间戳
        public bool Update(MyDetectedEntityInfo entity, int update_time = 0){
            if(entity.EntityId == this.Id){
                this._target = entity;
                this.UpdateTime = update_time;
            }
            return false;
        }
        public bool Update(Camera.Target target, int update_time = 0){
            return this.Update(target._target, update_time);
        }
    }
}

class Cameras
{
    // v1.0.0
    // 依赖： Camera -> Block

    // == 构造方法
    // 传入一个主控块（）安考查
    public Cameras(Block main_block, List<Camera> cams){
        this.MainBlock = main_block;
        this._cameras = new List<Camera>();
        this._cameras = cams;
    }

    // == 成员属性
    public Block MainBlock; //主体方块
    public List<Camera> _cameras; //主体

    // == 成员方法
    //
}

class Gyro: Block
{
    // v1.0.0
    // 依赖：Block类

    // == 构造方法
    public Gyro(IMyTerminalBlock b):base(b){
        this._block = b;
        this._gyro = b as IMyGyro;
    }
    public Gyro(IMyGyro b):base(b){
        this._block = b;
        this._gyro = b as IMyGyro;
    }

    // == 成员属性
    public IMyGyro _gyro; //陀螺仪方块本体
    public double Pwoer{ //能量
        get { return this._gyro.GyroPower; }
        set { this._gyro.GyroPower = (float)value; }
    }
    public bool IsOverride{ //是否开启越级
        get { return this._gyro.GyroOverride; }
        set { this._gyro.GyroOverride = value; }
    }
    public int MotionRatio = 1; //正反系数
    public double Yaw{ //偏航值，开启越级后有效
        get { return this._gyro.Yaw*this.MotionRatio; }
        set { this._gyro.Yaw = (float)value*this.MotionRatio; }
    }
    public double Pitch{ //俯仰值，开启越级后有效
        get { return this._gyro.Pitch*this.MotionRatio; }
        set { this._gyro.Pitch = (float)value*this.MotionRatio; }
    }
    public double Roll{ //滚转值，开启越级后有效
        get { return this._gyro.Roll*this.MotionRatio; }
        set { this._gyro.Roll = (float)value*this.MotionRatio; }
    }
}

class Thrust: Block
{
    // v1.0.0
    // 依赖：Block类

    // == 构造方法
    public Thrust(IMyTerminalBlock b):base(b){
        this._block = b;
        this._thrust = b as IMyThrust;
    }
    public Thrust(IMyThrust b):base(b){
        this._block = b;
        this._thrust = b as IMyThrust;
    }

    // == 成员属性
    public IMyThrust _thrust; //推进器方块本体
    public double Power{ //越级出力值（单位：百分比）
        get { return this._thrust.ThrustOverridePercentage; }
        set { this._thrust.ThrustOverridePercentage = (float)value; }
    }
    public double PowerN{ //越级出力值（单位：牛顿）
        get { return this._thrust.ThrustOverride; }
        set { this._thrust.ThrustOverride = (float)value; }
    }
    public double MaxThrust{ //最大出力值（单位：牛顿）
        get { return this._thrust.MaxThrust; }
    }
    public double MaxEffectiveThrust{ //最大实际出力值（单位：牛顿）
        get { return this._thrust.MaxEffectiveThrust; }
    }
    public double CurrentThrust{ //当前出力值（单位：牛顿）
        get { return this._thrust.CurrentThrust; }
    }
    public Vector3I GridThrustDirection{ //基于网格方向的相对方向，相当于安装方向
        get { return this._thrust.GridThrustDirection; }
    }
}

class Piston: Block
{
    // v1.0.0
    // 依赖：Block类

    // == 构造方法
    public Piston(IMyTerminalBlock b):base(b){
        this._block = b;
        this._piston = b as IMyPistonBase;
    }
    public Piston(IMyPistonBase b):base(b){
        this._block = b;
        this._piston = b as IMyPistonBase;
    }

    // == 成员属性
    public IMyPistonBase _piston; //活塞方块本体
    public double Velocity{ //速度
        get { return this._piston.Velocity; }
        set { this._piston.Velocity = (float)value; }
    }
    public double MaxVelocity{ //最大速度
        get { return this._piston.MaxVelocity; }
    }
    public double MinLimit{ //最小限制
        get { return this._piston.MinLimit; }
        set { this._piston.MinLimit = (float)value; }
    }
    public double MaxLimit{ //最大限制
        get { return this._piston.MaxLimit; }
        set { this._piston.MaxLimit = (float)value; }
    }
    public double CurrentPosition{ //当前位置
        get { return this._piston.CurrentPosition; }
    }
    public PistonStatus Status{ //当前状态
        get { return this._piston.Status; }
    }
}

